package com.solarStruggle.graphics

import java.awt.{Color}
import util.Random

object ColorSpec {
  val Invariant = (0.0f, 0.0f)
  val Unconstrained = (-1.0f, 1.0f)
  def VaryBy(n: Float) = (-n, n)
}

/**
 * Defines the spec for a random color.  Each element of the color is multiplied by a value inside
 * of luminosity range, then each resulting element is multiplied again independently by a random
 * number inside rgbRange.  Finally the resulting color's alpha value is set to a value inside
 * of alphaRange
 */
case class ColorSpec(baseColor: Color, 
	lDeltaRange: (Float, Float), 
	rgbDeltaRange: (Float, Float), 
	aDeltaRange: (Float, Float)) {

	def getColor(r: Random): Color = {
    def getSample(origVal: Int, lVal: Float, deltaRange: (Float, Float)): Int =
      Math.min(Math.max(
        origVal.toFloat * (1.0f + lVal + r.nextRangedFloat(deltaRange._1, deltaRange._2))
      , 0.0f), 255.0f).toInt
    
    val deltaL = r.nextRangedFloat(lDeltaRange._1, lDeltaRange._2)
    new Color(getSample(baseColor.getRed, deltaL, rgbDeltaRange),
              getSample(baseColor.getGreen, deltaL, rgbDeltaRange),
              getSample(baseColor.getBlue, deltaL, rgbDeltaRange),
              getSample(baseColor.getAlpha, 0.0f, aDeltaRange))
	}
}

/**
 * This class describes a set of colorSpecs for creating a random color.  Each colorSpec has a
 * probability assigned to it.  The default spec is used for the "rest" of the possibilities, in
 * which no other probability matched
 */
case class RandomColorDescriptor(defaultSpec: ColorSpec, specs: (Float, ColorSpec)*) {

	def getColor(r: Random): Color = {
		val specR = r.nextFloat()
		var specStart = 0.0f
		var foundSpec: Option[ColorSpec] = None

		for(spec <- specs) {
			if(specR > specStart && specR < specStart + spec._1)
				foundSpec = Some(spec._2)
			specStart += spec._1
		}

		if(foundSpec.isEmpty) {
			foundSpec = Some(defaultSpec)
		}

		foundSpec.get.getColor(r)
	}

}
